import { watcher } from "@feng3d/watcher";
import { MeshPhongMaterial } from "../../thirdparty/three/imports";
import { Texture3D } from "../textures/Texture3D";
import { Material3D } from "./Material3D";

export interface MeshPhongMaterial3D
{
    get _material(): MeshPhongMaterial;
    set _material(v: MeshPhongMaterial);
}

export class MeshPhongMaterial3D extends Material3D
{
    map: Texture3D;

    get color()
    {
        return this._material.color;
    }
    set color(v)
    {
        this._material.color = v;
    }

    get specular()
    {
        return this._material.specular;
    }
    set specular(v)
    {
        this._material.specular = v;
    }

    get shininess()
    {
        return this._material.shininess;
    }
    set shininess(v)
    {
        this._material.shininess = v;
    }

    get emissive()
    {
        return this._material.emissive;
    }
    set emissive(v)
    {
        this._material.emissive = v;
    }

    get normalMap()
    {
        return Texture3D.get(this._material.normalMap);
    }
    set normalMap(v)
    {
        this._material.normalMap = v._texture;
    }

    get specularMap()
    {
        return Texture3D.get(this._material.specularMap);
    }
    set specularMap(v)
    {
        this._material.specularMap = v._texture;
    }

    get normalScale()
    {
        return this._material.normalScale;
    }
    set normalScale(v)
    {
        this._material.normalScale = v;
    }

    get wireframe()
    {
        return this._material.wireframe;
    }
    set wireframe(v)
    {
        this._material.wireframe = v;
    }

    get flatShading()
    {
        return this._material.flatShading;
    }
    set flatShading(v)
    {
        this._material.flatShading = v;
    }

    get envMap()
    {
        return Texture3D.get(this._material.envMap);
    }
    set envMap(v)
    {
        this._material.envMap = v._texture;
    }

    constructor()
    {
        super();
        this._material = new MeshPhongMaterial();
        MeshPhongMaterial3D._map.set(this._material, this);
        watcher.watchobject(this as MeshPhongMaterial3D, { map: { _texture: null } }, this._onMapChanged, this);
    }

    destroy()
    {
        watcher.unwatchobject(this as MeshPhongMaterial3D, { map: { _texture: null } }, this._onMapChanged, this);

        super.destroy();
    }

    clone()
    {
        const meshPhongMaterial = this._material.clone();
        const meshPhongMaterial3D = MeshPhongMaterial3D.get(meshPhongMaterial);

        return meshPhongMaterial3D;
    }

    private _onMapChanged()
    {
        this._material.map = this.map?._texture;
    }

    static get(meshPhongMaterial: MeshPhongMaterial)
    {
        let meshPhongMaterial3D = this._map.get(meshPhongMaterial) as MeshPhongMaterial3D;

        if (!meshPhongMaterial3D)
        {
            meshPhongMaterial3D = new MeshPhongMaterial3D();
            meshPhongMaterial3D._material = meshPhongMaterial;
        }

        return meshPhongMaterial3D;
    }
}
